/*
 *  Copyright (C) 1998-2020 by Northwoods Software Corporation. All Rights Reserved.
 */

import * as go from 'gojs';

import './Diagram.scss';
import linkImg from '../../assets/link.svg';
import closeIcon from '../../assets/close.svg';
// 组件图标icon
import attentionIcon from '../../assets/icons/attention.svg';
import collectIcon from '../../assets/icons/collect.svg';
import conditionIcon from '../../assets/icons/condition.svg';
import endIcon from '../../assets/icons/end.svg';
import interfaceIcon from '../../assets/icons/interface.svg';
import personIcon from '../../assets/icons/person.svg';
import presskeyIcon from '../../assets/icons/presskey.svg';
import skipIcon from '../../assets/icons/skip.svg';

/**
 * Diagram initialization method, which is passed to the ReactDiagram component.
 * This method is responsible for making the diagram and initializing the model, any templates,
 * and maybe doing other initialization tasks like customizing tools.
 * The model's data should not be set here, as the ReactDiagram component handles that.
 * 图表初始化: 初始化模型, 制作图表
 */
export function makeDiagramModal(config?: { isView?: boolean; isDebug?: boolean }): go.Diagram {
  // console.log('【Diagram组件】>>>>>>>>makeDiagramModal===图表初始化: 初始化模型, 制作图表');
  const $ = go.GraphObject.make;
  // 初始化图表
  const myDiagram = $(
    go.Diagram, // must name or refer to the DIV HTML element
    // 图表的基本配置
    {
      // margin: new go.Margin(0, 0, 0, 0),
      allowDrop: config?.isDebug || config?.isView ? false : true, // 是否允许拖拽
      allowCopy: config?.isDebug || config?.isView ? false : true, // 是否允许复制
      allowDelete: config?.isDebug || config?.isView ? false : true, // 是否允许删除
      // autoScale: go.Diagram.UniformToFill, // 自适应，单一方向出滚动条，不支持缩放
      // autoScale: go.Diagram.Uniform, //自适应，整体缩放显示在容器内部，不支持缩放
      scrollsPageOnFocus: true, // 滚动页焦点
      isReadOnly: config?.isDebug || config?.isView ? true : false, // 是否只读
      // "draggingTool.dragsLink": true, // 拖动工具拖动链接
      'draggingTool.isGridSnapEnabled': true, // 拖动工具已启用网格捕捉
      'animationManager.isEnabled': false, // 取消加载动画
      'linkingTool.isUnconnectedLinkValid': false, // 链接工具未连接链接有效
      'linkingTool.portGravity': 200, // 链接工具端口重力
      'relinkingTool.isUnconnectedLinkValid': true, // 重新连接工具未连接链接有效
      'relinkingTool.portGravity': 250, // 重新连接工具端口重力
      // 选中连接线: 出口箭头样式
      'relinkingTool.fromHandleArchetype': $(go.Shape, 'Diamond', {
        segmentIndex: 0,
        cursor: 'pointer',
        desiredSize: new go.Size(8, 8),
        fill: 'tomato',
        stroke: 'darkred',
      }),
      // 选中连接线: 入口箭头样式
      'relinkingTool.toHandleArchetype': $(go.Shape, 'Diamond', {
        segmentIndex: -1,
        cursor: 'pointer',
        desiredSize: new go.Size(8, 8),
        fill: 'darkred',
        stroke: 'tomato',
      }),
      // 选中连接线: 中间节点的样式
      'linkReshapingTool.handleArchetype': $(go.Shape, 'Diamond', {
        desiredSize: new go.Size(7, 7),
        fill: 'lightblue',
        stroke: 'deepskyblue',
      }),
      'rotatingTool.snapAngleMultiple': 15, //角度
      'rotatingTool.snapAngleEpsilon': 15,
      'undoManager.isEnabled': true, // 支持键盘事件
    }
  );

  // when the document is modified, add a "*" to the title and enable the "Save" button
  // 图表改变, 添加星号给title, 设置保存按钮可用
  // myDiagram.addDiagramListener('Modified', function (e) {
  //   const button = document.getElementById('SaveButton');
  //   if (button) button.disabled = !myDiagram.isModified;
  //   const idx = document.title.indexOf('*');
  //   if (myDiagram.isModified) {
  //     if (idx < 0) document.title += '*';
  //   } else {
  //     if (idx >= 0) document.title = document.title.substr(0, idx);
  //   }
  // });

  // 设置节点位置风格, 与数据loc属性绑定, 初始化各个节点模板时使用
  function nodeStyle() {
    return [
      // 将节点位置信息 Node.location 同节点模型数据中 "loc" 属性绑定：
      // 节点位置信息从 节点模型 "loc" 属性获取, 并由静态方法 Point.parse 解析.
      // 如果节点位置改变了, 会自动更新节点模型中"loc"属性, 并由 Point.stringify 方法转化为字符串
      new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
      {
        // 节点位置 Node.location 定位在节点的中心
        locationSpot: go.Spot.Center,
        background: '#fff',
        zOrder: 1,
        defaultAlignment: go.Spot.Top,
      },
    ];
  }
  // 节点删除按钮
  function makeNodeDeleteButton() {
    if (config?.isDebug || config?.isView) {
      // 调试的时候，不显示删除按钮，不能操作删除
      return [];
    }
    return $(
      go.Picture, // flag image, only visible if a nation is specified
      {
        column: 2,
        alignment: go.Spot.Right,
        margin: new go.Margin(-2, 9, 0, 0),
        visible: true,
        desiredSize: new go.Size(12, 12),
        source: closeIcon,
        click: function (e: any, obj: any) {
          myDiagram.clearSelection();
          // 删除该接点
          const node = obj.part;
          if (node !== null) {
            myDiagram.startTransaction('remove dept');
            myDiagram.remove(node);
            myDiagram.commitTransaction('remove dept');
          }
        },
      }
    );
  }

  // Port是透明长方形图块, 鼠标移动到边缘高亮显示
  // Define a function for creating a "port" that is normally transparent.
  // 定义用于创建通常透明的“端口”的函数
  // The "name" is used as the GraphObject.portId,
  // name是GraphObject的端口Id
  // the "align" is used to determine where to position the port relative to the body of the node,
  // "align": 决定"port" 属于节点4条边的哪条
  // the "spot" is used to control how links connect with the port and whether the port
  // spot控制连线连入/连出的位置
  // stretches along the side of the node,
  // 沿着节点边延伸
  // and the boolean "output" and "input" arguments control whether the user can draw links from or to the port.
  // output和input是否允许连线从此"port"连入或连出
  function makePort(name: string, align: go.Spot, spot: go.Spot, output: boolean, input: boolean) {
    // console.log('Diagram -> makePort');
    const horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
    // the port is basically just a transparent rectangle that stretches along the side of the node,
    // 该端口基本上只是一个沿着节点的边延伸的透明矩形
    // and becomes colored when the mouse passes over it
    // 鼠标经过变颜色
    return $(go.Shape, {
      fill: 'transparent', // 默认透明
      strokeWidth: 0, // 无边框
      width: 1, // 垂直"port"则1像素宽
      height: 1, // 水平"port"则1像素
      alignment: align, // 端口同其节点对齐
      stretch: horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical, // 自动同其节点一同伸缩
      portId: name, // 声明端口Id
      fromSpot: spot, // 声明连线头连出此"port"的位置
      fromLinkable: output, // 是否允许连线从此"port"连出
      toSpot: spot, // 声明连线尾连入此"port"的位置
      toLinkable: input, // 是否允许连线从此"port"连出
      cursor: 'pointer', // 鼠标由指针改为手指，表示此处可点击生成连线
      // 鼠标移到"port"位置后，高亮
      mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
        // the PORT argument will be this Shape
        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
        if (!e.diagram.isReadOnly) port.fill = 'rgba(255,0,255,0.5)';
        // port.background = "rgba(255,0,255,0.5)";
      },
      // 鼠标移出"port"位置后，透明
      mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
        port.fill = 'transparent';
      },
    });
  }

  function makePortOut(
    name: string,
    align: go.Spot,
    spot: go.Spot,
    output: boolean,
    input: boolean
  ) {
    const horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
    // the port is basically just a transparent rectangle that stretches along the side of the node,
    // and becomes colored when the mouse passes over it
    // 端口是透明矩形, 鼠标经过高亮显示
    return $(go.Shape, {
      fromMaxLinks: 1,
      fill: 'transparent', // changed to a color in the mouseEnter event handler
      strokeWidth: 0, // no stroke
      width: NaN, // if not stretching horizontally, just 8 wide
      height: 8, // if not stretching vertically, just 8 tall
      alignment: align, // align the port on the main Shape
      stretch: horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical,
      portId: name, // declare this object to be a "port"
      fromSpot: spot, // declare where links may connect at this port
      fromLinkable: output, // declare whether the user may draw links from here
      toSpot: spot, // declare where links may connect at this port
      toLinkable: input, // declare whether the user may draw links to here
      cursor: 'pointer', // show a different cursor to indicate potential link point
      mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
        // the PORT argument will be this Shape
        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
        if (!e.diagram.isReadOnly) port.fill = 'rgba(255,0,255,0.2)';
      },
      mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
        port.fill = 'transparent';
      },
    });
  }

  // define the Node templates for regular nodes
  // var mt8 = new go.Margin(8, 0, 0, 0);
  const mr8 = new go.Margin(0, 8, 0, 0);
  // var ml8 = new go.Margin(0, 0, 0, 8);

  /**
   * 组件宽度
   */
  const lineMinWidth = 180;

  /**
   * 跳转组件宽度
   */
  const skipWidth = 180;
  /**
   * 组件icon转换
   */
  function theIconFlagConverter(icon: any) {
    // console.log(icon, "图标名称");
    let path = '';

    switch (icon) {
      case 'attention':
      case 'Russia':
        path = attentionIcon;
        break;
      case 'collect':
      case 'CzechRepublic':
        path = collectIcon;
        break;
      case 'condition':
      case 'Ireland':
        path = conditionIcon;
        break;
      case 'end':
      case 'Georgia':
        path = endIcon;
        break;
      case 'interface':
      case 'Denmark':
        path = interfaceIcon;
        break;
      case 'person':
      case 'Argentina':
        path = personIcon;
        break;
      case 'presskey':
      case 'Norway':
        path = presskeyIcon;
        break;
      case 'skip':
        path = skipIcon;
        break;
      default:
        path = linkImg;
    }
    return path;
  }

  const roundedRectangleParams = {
    parameter1: 2, // set the rounded corner
    spot1: go.Spot.TopLeft,
    spot2: go.Spot.BottomRight, // make content go all the way to inside edges of rounded corners
  };

  // 图形上的文字风格
  function textStyle(field: string) {
    return [
      {
        font: '12px Roboto, sans-serif',
        stroke: 'rgba(0, 0, 0, .60)',
        visible: false, // 只有在文本块有相应数据时才显示文本块
      },
      new go.Binding('visible', field, function (val) {
        return val !== undefined;
      }),
    ];
  }
  /**组件状态改变：0正常，1高亮，2错误*/
  function nodeStatusConverter(s: number) {
    if (s === 1) return '#1090ff';
    if (s === 2) return 'red';
    return 'white';
  }
  // 组件内元素状态改变，如单个条件 或者 单个意图
  function itemStatusConverter(s: number) {
    if (s === 1) return '#1090ff';
    if (s === 2) return 'red';
    return '#DCEAFC';
  }

  // 显示项根据参数过滤：默认全部显示。eg：按键组件：收号和按键，底部按钮区分
  function showIntentList(keyFlagValue: string) {
    return [
      {
        visible: false, // only show textblocks when there is corresponding data for them
      },
      new go.Binding('visible', 'keyFlag', function (val) {
        return val === keyFlagValue;
      }),
    ];
  }

  // 开始组件
  myDiagram.nodeTemplateMap.add(
    'StartComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      {
        deletable: false, // 禁止删除
        copyable: false, // 禁止复制
        maxSize: new go.Size(123, 44),
        locationSpot: go.Spot.Top,
        isShadowed: true,
        shadowBlur: 1,
        shadowOffset: new go.Point(0, 1),
        shadowColor: 'rgba(0, 0, 0, .14)',
        // selection adornment to match shape of nodes
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff',
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
        // new go.AnimationTrigger("stroke")
      ),
      // $(
      //   go.Shape,
      //   'RoundedRectangle',
      //   roundedRectangleParams,
      //   { name: 'SHAPE', fill: '#ffffff', strokeWidth: 0 },
      //   // bluish if highlighted, white otherwise
      //   // 高亮蓝色, 其他白色
      //   new go.Binding('fill', 'isHighlighted', function (h) {
      //     return h ? '#e8eaf6' : '#ffffff';
      //   }).ofObject()
      // ),
      $(
        go.TextBlock,
        {
          font: '14px Roboto, sans-serif',
          stroke: '#F75050',
          textAlign: 'center',
          margin: new go.Margin(0, 0, 0, 0),
          visible: true,
          editable: false,
          alignment: go.Spot.Center,
        },
        new go.Binding('text', 'name')
      ),
      // 下面只能出, 不能入
      makePortOut('B', go.Spot.Bottom, go.Spot.Bottom, true, false)
    )
  );

  // 意图组件
  myDiagram.nodeTemplateMap.add(
    'IntentComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      {
        locationSpot: go.Spot.Top,
        margin: 0,
        isShadowed: true,
        shadowBlur: 1,
        alignment: go.Spot.Top,
        //width: 180,
        //height: 94,
        shadowOffset: new go.Point(0, 1),
        shadowColor: 'rgba(0, 0, 0, .14)',
        // 自定义选中边框模版
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff',
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            // height: 29,
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
            //defaultAlignment: go.Spot.Left
          },
          $(
            go.Panel,
            'Horizontal',
            {
              // height: 29,
              stretch: go.GraphObject.Horizontal,
              margin: new go.Margin(0, 0, 0, 0),
              //defaultAlignment: go.Spot.Left
            },
            $(
              go.Picture, // flag image, only visible if a nation is specified
              {
                column: 0,
                margin: new go.Margin(0, 4, 0, 0),
                // visible: false,
                // desiredSize: new go.Size(45, 45),
                width: 25,
                height: 25,
                source: linkImg,
              },
              new go.Binding('source', 'icon', theIconFlagConverter),
              new go.Binding('visible', 'icon', function (nat) {
                return nat !== undefined;
              })
            ),
            // 标题文字
            $(
              go.TextBlock,
              {
                column: 1,
                //width: 80,
                alignment: go.Spot.Left,
                name: 'TB',
                textAlign: 'left',
                font: '14px PingFangSC-Medium, arial, sans-serif',
                stroke: '#474A50',
                editable: false,
                margin: new go.Margin(0, 0, 0, 0),
              },
              new go.Binding('text', 'title')
            )
          ),
          makeNodeDeleteButton()
        ),
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(lineMinWidth, 1),
            //maxSize: new go.Size(lineMinWidth, 1),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),
        $(
          go.TextBlock,
          textStyle('script'),
          {
            textAlign: 'center',
            margin: new go.Margin(10, 0, 10, 0),
            editable: false,
            visible: true,
            alignment: go.Spot.Center,
            //minSize: new go.Size(170, NaN),
            maxSize: new go.Size(170, NaN),
            isMultiline: true, //是否多行
            //maxSize: new go.Size(1000, NaN)
          },
          new go.Binding('text', 'script', function (script) {
            return script || '请先编辑组件';
          }).makeTwoWay()
        ),
        // 底部：意图按钮
        $(
          go.Panel,
          'Horizontal',
          {
            alignment: go.Spot.Bottom,
            margin: new go.Margin(10, 0, 0, 0),
          },
          $(go.Panel, 'Horizontal', new go.Binding('itemArray', 'intentionArray'), {
            itemTemplate: $(
              go.Panel,
              {
                margin: new go.Margin(0, 5),
                fromLinkable: true,
                toLinkable: false,
                fromLinkableDuplicates: true,
                toLinkableDuplicates: false,
                fromSpot: go.Spot.Bottom,
                toSpot: go.Spot.Bottom,
                fromMaxLinks: 1,
                toMaxLinks: 0,
                cursor: 'pointer',
                mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                  // the PORT argument will be this Shape
                  // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                  port.fill = 'rgba(255,0,255,0.5)';
                },
                mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                  // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                  port.fill = 'transparent';
                },
              },
              new go.Binding('portId', 'text'),
              $(
                go.Panel,
                'Auto',
                $(
                  go.Shape,
                  'Rectangle',
                  {
                    //fill: '#DCEAFC',
                    //stroke: null,
                    fill: '#FFFFFF',
                    stroke: '#DCEAFC',
                  },
                  new go.Binding('stroke', 'status', itemStatusConverter) // 按键高亮框
                ),
                $(
                  go.TextBlock,
                  {
                    margin: 5,
                    stroke: '#1883D7',
                    font: '12px sans-serif',
                    mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                      // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                      // the PORT argument will be this Shape
                      port.stroke = '#F883D7';
                    },
                    mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                      // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                      port.stroke = '#1883D7';
                    },
                  },
                  new go.Binding('text', 'text')
                )
              )
            ),
          })
        )
      ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true)
    )
  );

  // 按键组件
  myDiagram.nodeTemplateMap.add(
    'KeyComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      {
        locationSpot: go.Spot.Top,
        margin: 0,
        isShadowed: true,
        shadowBlur: 1,
        alignment: go.Spot.Top,
        //width: 180,
        shadowOffset: new go.Point(0, 1),
        shadowColor: 'rgba(0, 0, 0, .14)',
        // selection adornment to match shape of nodes
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff',
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
            // height: 29,
            //defaultAlignment: go.Spot.TopLeft
          },
          $(
            go.Panel,
            'Horizontal',
            {
              // height: 29,
              stretch: go.GraphObject.Horizontal,
              margin: new go.Margin(0, 0, 0, 0),
              //defaultAlignment: go.Spot.Left
            },
            $(
              go.Picture, // flag image, only visible if a nation is specified
              {
                column: 0,
                margin: new go.Margin(0, 4, 0, 0),
                width: 25,
                height: 25,
                source: linkImg,
              },
              new go.Binding('source', 'icon', theIconFlagConverter),
              new go.Binding('visible', 'icon', function (nat) {
                return nat !== undefined;
              })
            ),
            $(
              go.TextBlock,
              {
                column: 1,
                alignment: go.Spot.Left,
                name: 'TB',
                textAlign: 'left',
                font: '14px PingFangSC-Medium, arial, sans-serif',
                stroke: '#474A50',
                editable: false,
                margin: new go.Margin(0, 0, 0, 0),
              },
              new go.Binding('text', 'title')
            )
          ),
          makeNodeDeleteButton()
        ),
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(lineMinWidth, NaN),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),
        $(
          go.TextBlock,
          textStyle('script'),
          {
            textAlign: 'center',
            margin: new go.Margin(10, 0, 0, 0),
            editable: false,
            visible: true,
            alignment: go.Spot.Center,
            maxSize: new go.Size(170, NaN),
          },
          new go.Binding('text', 'script', function (script) {
            return script || '请先编辑组件';
          }).makeTwoWay() // 双向绑定
        ),
        $(
          go.Panel,
          'Horizontal',
          {
            alignment: go.Spot.Bottom,
            margin: new go.Margin(10, 0, 0, 0),
          },
          // 方式：按键
          $(
            go.Panel,
            'Horizontal',
            showIntentList('PressKey'),
            new go.Binding('itemArray', 'pressKeyArray'),
            {
              itemTemplate: $(
                go.Panel,
                {
                  margin: new go.Margin(0, 5),
                  fromLinkable: true,
                  toLinkable: false,
                  fromLinkableDuplicates: true,
                  toLinkableDuplicates: false,
                  fromSpot: go.Spot.Bottom,
                  toSpot: go.Spot.Bottom,
                  fromMaxLinks: 1,
                  toMaxLinks: 0,
                  cursor: 'pointer',
                  mouseEnter: function (e, port) {
                    // the PORT argument will be this Shape
                    // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                    port.fill = 'rgba(255,0,255,0.5)';
                  },
                  mouseLeave: function (e, port) {
                    // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                    port.fill = 'transparent';
                  },
                },
                new go.Binding('portId', 'key'),
                $(
                  go.Panel,
                  'Auto',
                  $(
                    go.Shape,
                    'Rectangle',
                    {
                      //fill: '#DCEAFC',
                      //stroke: null,
                      fill: '#FFFFFF',
                      stroke: '#DCEAFC',
                    },
                    new go.Binding('stroke', 'status', itemStatusConverter) // 按键高亮框
                  ),
                  $(
                    go.TextBlock,
                    {
                      margin: 5,
                      stroke: '#1883D7',
                      font: '12px sans-serif',
                      mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                        // the PORT argument will be this Shape
                        port.stroke = '#F883D7';
                      },
                      mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                        port.stroke = '#1883D7';
                      },
                    },
                    new go.Binding('text', 'key')
                  )
                )
              ),
            }
          ),
          // 方式：收号
          $(
            go.Panel,
            'Horizontal',
            showIntentList('ReceiveNumber'),
            new go.Binding('itemArray', 'receiveNumberDefaultArray'),
            {
              itemTemplate: $(
                go.Panel,
                {
                  margin: 5,
                  fromLinkable: true,
                  toLinkable: false,
                  fromLinkableDuplicates: true,
                  toLinkableDuplicates: false,
                  fromSpot: go.Spot.Bottom,
                  toSpot: go.Spot.Bottom,
                  fromMaxLinks: 1,
                  toMaxLinks: 0,
                  cursor: 'pointer',
                  mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                    // the PORT argument will be this Shape
                    // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                    port.fill = 'rgba(255,0,255,0.5)';
                  },
                  mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                    // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                    port.fill = 'transparent';
                  },
                },
                // 收号:底部按钮
                new go.Binding('portId', 'intent'),
                $(
                  go.Panel,
                  'Auto',
                  $(
                    go.Shape,
                    'Rectangle',
                    {
                      //fill: '#DCEAFC',
                      //stroke: null,
                      fill: '#FFFFFF',
                      stroke: '#DCEAFC',
                    },
                    new go.Binding('stroke', 'status', itemStatusConverter) // 按键高亮框
                  ),
                  $(
                    go.TextBlock,
                    {
                      margin: 5,
                      stroke: '#1883D7',
                      font: '12px sans-serif',
                      mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                        // the PORT argument will be this Shape
                        port.stroke = '#F883D7';
                      },
                      mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                        port.stroke = '#1883D7';
                      },
                    },
                    new go.Binding('text', 'intent')
                  )
                )
              ),
            }
          )
        )
        //                        )
      ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true)
    )
  );

  // 条件组件
  myDiagram.nodeTemplateMap.add(
    'ConditionComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      {
        locationSpot: go.Spot.Top,
        isShadowed: true,
        shadowBlur: 1,
        shadowOffset: new go.Point(0, 1),
        shadowColor: 'rgba(0, 0, 0, .14)',
        // selection adornment to match shape of nodes
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff',
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
            //defaultAlignment: go.Spot.TopLeft
          },
          $(
            go.Panel,
            'Horizontal',
            {
              stretch: go.GraphObject.Horizontal,
              margin: new go.Margin(0, 0, 0, 0),
            },
            // 连接图标
            $(
              go.Picture, // flag image, only visible if a nation is specified
              {
                column: 0,
                margin: new go.Margin(0, 4, 0, 0),
                width: 25,
                height: 25,
                visible: true,
                // source: linkImg, // 打开页面会报错，不知道为啥？？？
              },
              new go.Binding('source', 'icon', theIconFlagConverter),
              new go.Binding('visible', 'icon', function (nat) {
                return nat !== undefined;
              })
            ),
            // 组件标题
            $(
              go.TextBlock,
              {
                column: 1,
                alignment: go.Spot.Left,
                name: 'TB',
                textAlign: 'left',
                font: '14px PingFangSC-Medium, arial, sans-serif',
                stroke: '#474A50',
                editable: false,
              },
              new go.Binding('text', 'title')
            )
          ),
          makeNodeDeleteButton()
        ),
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(lineMinWidth, NaN),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),
        $(
          go.Panel,
          'Horizontal',
          {
            alignment: go.Spot.Bottom,
            margin: new go.Margin(10, 0, 0, 0),
          },
          // 初始语句
          $(
            go.TextBlock,
            // {
            //   text: "请先编辑组件",
            //   font: "15px Roboto, sans-serif",
            //   stroke: "rgba(0, 0, 0, .60)",
            // },
            textStyle('script'),
            {
              textAlign: 'left',
              text: '请先编辑组件',
              margin: new go.Margin(0, 0, 0, 0),
              maxSize: new go.Size(170, NaN),
              editable: false,
              visible: true,
              alignment: go.Spot.Left,
            },
            // 绑定visible属性与conditionArray字段的关联关系
            new go.Binding('visible', 'conditionArray', function (arr) {
              if (arr && arr.length) {
                return false;
              } else {
                return true;
              }
            })
          ),
          // 渲染条件按钮
          $(go.Panel, 'Horizontal', new go.Binding('itemArray', 'conditionArray'), {
            itemTemplate: $(
              go.Panel,
              {
                margin: 5,
                fromLinkable: true, // 允许连线出口
                toLinkable: false, // 不允许连线入口
                fromLinkableDuplicates: true,
                toLinkableDuplicates: false,
                fromSpot: go.Spot.Bottom, // 出口位置
                toSpot: go.Spot.Bottom, // 入口位置
                fromMaxLinks: 1, // 出线最多一个
                toMaxLinks: 0, // 入线0个
                cursor: 'pointer',
                mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                  // the PORT argument will be this Shape
                  // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                  // port.fill = "rgba(255,0,255,0.5)";
                  port.background = 'rgba(255,0,255,0.5)';
                },
                mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                  // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                  // port.fill = "transparent";
                  port.background = 'transparent';
                },
              },
              new go.Binding('portId', 'describe'),
              $(
                go.Panel,
                'Auto',
                $(
                  go.Shape,
                  'Rectangle',
                  {
                    fill: '#FFFFFF',
                    stroke: '#DCEAFC',
                  },
                  new go.Binding('stroke', 'status', itemStatusConverter) // 条件高亮框
                ),
                $(
                  go.TextBlock,
                  {
                    margin: 5,
                    stroke: '#1883D7',
                    font: '12px sans-serif',
                    mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                      // the PORT argument will be this Shape
                      // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                      port.stroke = '#F883D7';
                    },
                    mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                      // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                      port.stroke = '#1883D7';
                    },
                  },
                  new go.Binding('text', 'describe')
                )
              )
            ),
          })
        )
      ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true)
    )
  );

  // 接口组件
  myDiagram.nodeTemplateMap.add(
    'InterfaceComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      {
        locationSpot: go.Spot.Top,
        isShadowed: true,
        shadowBlur: 1,
        shadowOffset: new go.Point(0, 1),
        shadowColor: 'rgba(0, 0, 0, .14)',
        // selection adornment to match shape of nodes
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff',
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
          },
          $(
            go.Panel,
            'Horizontal',
            {
              stretch: go.GraphObject.Horizontal,
              margin: new go.Margin(0, 0, 0, 0),
            },
            // 连接图标
            $(
              go.Picture, // flag image, only visible if a nation is specified
              {
                column: 0,
                margin: new go.Margin(0, 4, 0, 0),
                width: 25,
                height: 25,
                visible: true,
                // source: linkImg, // 打开页面会报错，不知道为啥？？？
              },
              new go.Binding('source', 'icon', theIconFlagConverter),
              new go.Binding('visible', 'icon', function (nat) {
                return nat !== undefined;
              })
            ),
            // 组件标题
            $(
              go.TextBlock,
              {
                column: 1,
                alignment: go.Spot.Left,
                name: 'TB',
                textAlign: 'left',
                font: '14px PingFangSC-Medium, arial, sans-serif',
                stroke: '#474A50',
                editable: false,
              },
              new go.Binding('text', 'title')
            )
          ),
          makeNodeDeleteButton()
        ),
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(lineMinWidth, NaN),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),
        $(
          go.TextBlock,
          {
            font: '12px Roboto, sans-serif',
            stroke: 'rgba(0, 0, 0, .60)',
            textAlign: 'center',
            margin: new go.Margin(10, 0, 0, 0),
            maxSize: new go.Size(170, NaN),
            editable: false,
            visible: true,
            alignment: go.Spot.Center,
            //maxSize: new go.Size(1000, NaN)
          },
          new go.Binding('text', 'interfaceInfo', function (obj) {
            if (obj && obj.name) {
              return '调用' + obj.name + '接口';
            } else {
              return '请先编辑组件';
            }
          })
        )
      ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true),
      makePortOut('B', go.Spot.Bottom, go.Spot.Bottom, true, false)
    )
  );

  // 转人工组件
  myDiagram.nodeTemplateMap.add(
    'TransferManualServiceComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      {
        locationSpot: go.Spot.Top,
        isShadowed: true,
        shadowBlur: 1,
        shadowOffset: new go.Point(0, 1),
        shadowColor: 'rgba(0, 0, 0, .14)',
        // selection adornment to match shape of nodes
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff',
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
          },
          $(
            go.Panel,
            'Horizontal',
            {
              stretch: go.GraphObject.Horizontal,
              margin: new go.Margin(0, 0, 0, 0),
            },
            // 连接图标
            $(
              go.Picture, // flag image, only visible if a nation is specified
              {
                column: 0,
                margin: new go.Margin(0, 4, 0, 0),
                width: 25,
                height: 25,
                visible: true,
                // source: linkImg, // 打开页面会报错，不知道为啥？？？
              },
              new go.Binding('source', 'icon', theIconFlagConverter),
              new go.Binding('visible', 'icon', function (nat) {
                return nat !== undefined;
              })
            ),
            // 组件标题
            $(
              go.TextBlock,
              {
                column: 1,
                alignment: go.Spot.Left,
                name: 'TB',
                textAlign: 'left',
                font: '14px PingFangSC-Medium, arial, sans-serif',
                stroke: '#474A50',
                editable: false,
              },
              new go.Binding('text', 'title')
            )
          ),
          makeNodeDeleteButton()
        ),
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(lineMinWidth, NaN),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),

        $(
          go.TextBlock,
          {
            font: '12px Roboto, sans-serif',
            stroke: 'rgba(0, 0, 0, .60)',
            textAlign: 'center',
            margin: new go.Margin(10, 0, 0, 0),
            maxSize: new go.Size(170, NaN),
            editable: false,
            visible: true,
            alignment: go.Spot.Center,
            //maxSize: new go.Size(1000, NaN)
          },
          new go.Binding('text', 'phoneNumber', function (str) {
            if (str == null || str === undefined || str.length <= 0) {
              return '请先编辑组件';
            } else {
              return '转号码：' + str;
            }
          })
        ),
        $(
          go.Panel,
          'Horizontal',
          {
            alignment: go.Spot.Bottom,
            margin: new go.Margin(10, 0, 0, 0),
          },
          // 人工结果
          $(go.Panel, 'Horizontal', new go.Binding('itemArray', 'transferManualIntentionArray'), {
            itemTemplate: $(
              go.Panel,
              {
                margin: 5,
                fromLinkable: true,
                toLinkable: false,
                fromLinkableDuplicates: true,
                toLinkableDuplicates: false,
                fromSpot: go.Spot.Bottom,
                toSpot: go.Spot.Bottom,
                fromMaxLinks: 1,
                toMaxLinks: 0,
                cursor: 'pointer',
                mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                  // the PORT argument will be this Shape
                  // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                  port.fill = 'rgba(255,0,255,0.5)';
                },
                mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                  // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                  port.fill = 'transparent';
                },
              },
              // 人工结果:底部按钮
              new go.Binding('portId', 'intent'),
              $(
                go.Panel,
                'Auto',
                $(
                  go.Shape,
                  'Rectangle',
                  {
                    //fill: '#DCEAFC',
                    //stroke: null,
                    fill: '#FFFFFF',
                    stroke: '#DCEAFC',
                  },
                  new go.Binding('stroke', 'status', itemStatusConverter) // 按键高亮框
                ),
                $(
                  go.TextBlock,
                  {
                    margin: 5,
                    stroke: '#1883D7',
                    font: '12px sans-serif',
                    mouseEnter: function (e: go.InputEvent, port: go.GraphObject) {
                      // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                      // the PORT argument will be this Shape
                      port.stroke = '#F883D7';
                    },
                    mouseLeave: function (e: go.InputEvent, port: go.GraphObject) {
                      // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
                      port.stroke = '#1883D7';
                    },
                  },
                  new go.Binding('text', 'intent')
                )
              )
            ),
          })
        )
      ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true)
    )
  );

  // 跳转组件
  myDiagram.nodeTemplateMap.add(
    'SkipComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      {
        locationSpot: go.Spot.Top,
        margin: 0,
        isShadowed: true,
        shadowBlur: 1,
        alignment: go.Spot.Top,
        // width: 400,
        shadowOffset: new go.Point(0, 1),
        shadowColor: 'rgba(0, 0, 0, .14)',
        // selection adornment to match shape of nodes
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff',
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
            // height: 29,
            //defaultAlignment: go.Spot.TopLeft
          },
          $(
            go.Panel,
            'Horizontal',
            {
              // height: 29,
              stretch: go.GraphObject.Horizontal,
              margin: new go.Margin(0, 0, 0, 0),
              //defaultAlignment: go.Spot.Left
            },
            $(
              go.Picture, // flag image, only visible if a nation is specified
              {
                column: 0,
                margin: new go.Margin(0, 4, 0, 0),
                width: 25,
                height: 25,
                source: linkImg,
              },
              new go.Binding('source', 'icon', theIconFlagConverter),
              new go.Binding('visible', 'icon', function (nat) {
                return nat !== undefined;
              })
            ),
            $(
              go.TextBlock,
              {
                column: 1,
                alignment: go.Spot.Left,
                name: 'TB',
                textAlign: 'left',
                font: '14px PingFangSC-Medium, arial, sans-serif',
                stroke: '#474A50',
                editable: false,
                margin: new go.Margin(0, 0, 0, 0),
              },
              new go.Binding('text', 'title')
            )
          ),
          makeNodeDeleteButton()
        ),
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(skipWidth, NaN),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),
        $(
          go.TextBlock,
          textStyle('script'),
          {
            textAlign: 'center',
            margin: new go.Margin(10, 0, 0, 0),
            editable: false,
            visible: true,
            alignment: go.Spot.Center,
            maxSize: new go.Size(skipWidth - 10, NaN),
          },
          new go.Binding('text', 'script', function (script) {
            return script || '请先编辑组件';
          }).makeTwoWay() // 双向绑定
        )
      ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true),
      makePortOut('B', go.Spot.Bottom, go.Spot.Bottom, true, false)
    )
  );

  // 信息收集组件
  myDiagram.nodeTemplateMap.add(
    'InfoCollectionComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      // 边框+阴影
      {
        locationSpot: go.Spot.Top,
        isShadowed: true, // 阴影
        shadowBlur: 1,
        shadowOffset: new go.Point(0, 1), // 阴影偏移
        shadowColor: 'rgba(0, 0, 0, .14)', // 阴影颜色
        // selection adornment to match shape of nodes
        // 选择装饰搭配节点的形状
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff', // 选中状态边框颜色
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      // 背景
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      // 面板
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
          },
          // 连接图标
          $(
            go.Picture, // flag image, only visible if a nation is specified
            { column: 0, margin: 0, width: 30, height: 30, source: linkImg },
            new go.Binding('source', 'icon', theIconFlagConverter),
            new go.Binding('visible', 'icon', function (nat) {
              return nat !== undefined;
            })
          ),
          // 组件标题
          $(
            go.TextBlock,
            {
              column: 1,
              alignment: go.Spot.Left,
              name: 'TB',
              textAlign: 'left',
              font: '14px PingFangSC-Medium, arial, sans-serif',
              stroke: '#474A50',
              editable: false,
            },
            new go.Binding('text', 'title')
          ),
          makeNodeDeleteButton()
        ),
        // 标题和内容的分割线
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(lineMinWidth, NaN),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),
        // 话术文案
        $(
          go.TextBlock,
          {
            font: '15px Roboto, sans-serif',
            stroke: 'rgba(0, 0, 0, .60)',
            textAlign: 'left',
            margin: new go.Margin(30, 30, 10, 30),
            maxSize: new go.Size(240, NaN),
            editable: false,
            visible: true,
            alignment: go.Spot.Left,
            //maxSize: new go.Size(1000, NaN)
          },
          new go.Binding('text', 'script', function (str) {
            if (str == null || str === undefined || str.length <= 0) {
              return '请先编辑组件';
            } else {
              return '话术：' + str;
            }
          })
        ),
        // 变量名
        $(
          go.TextBlock,
          {
            font: '15px Roboto, sans-serif',
            stroke: 'rgba(0, 0, 0, .60)',
            textAlign: 'left',
            margin: new go.Margin(10, 30, 10, 30),
            maxSize: new go.Size(200, NaN),
            visible: true,
            editable: false,
            alignment: go.Spot.Left,
            //maxSize: new go.Size(1000, NaN)
          },
          new go.Binding('text', 'variableName', function (str) {
            if (str == null || str === undefined || str.length <= 0) {
              return '';
            } else {
              return '变量名：' + str;
            }
          }),
          new go.Binding('visible', 'script', function (str) {
            if (str == null || str === undefined || str.length <= 0) {
              return false;
            } else {
              return true;
            }
          })
        )
      ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true),
      makePortOut('B', go.Spot.Bottom, go.Spot.Bottom, true, false)
    )
  );

  // 结束组件
  myDiagram.nodeTemplateMap.add(
    'EndComponent',
    $(
      go.Node,
      'Auto',
      nodeStyle(),
      // 边框+阴影
      {
        locationSpot: go.Spot.Top,
        isShadowed: true, // 阴影
        shadowBlur: 1,
        // height: 66, // 高度自适应，多行文字都完整显示
        shadowOffset: new go.Point(0, 1), // 阴影偏移
        shadowColor: 'rgba(0, 0, 0, .14)', // 阴影颜色
        // selection adornment to match shape of nodes
        // 选择装饰搭配节点的形状
        selectionAdornmentTemplate: $(
          go.Adornment,
          'Auto',
          $(go.Shape, 'RoundedRectangle', roundedRectangleParams, {
            fill: null,
            stroke: '#1890ff', // 选中状态边框颜色
            strokeWidth: 3,
          }),
          $(go.Placeholder)
        ), // end Adornment
      },
      // 背景
      $(
        go.Shape,
        'RoundedRectangle', // 接点增强显示
        { strokeWidth: 3, stroke: 'white', fill: 'white' },
        new go.Binding('stroke', 'status', nodeStatusConverter)
      ),
      // 面板
      $(
        go.Panel,
        'Vertical',
        $(
          go.Panel,
          'Table',
          {
            stretch: go.GraphObject.Horizontal,
            margin: new go.Margin(0, 0, 0, 0),
          },
          $(
            go.Panel,
            'Horizontal',
            {
              stretch: go.GraphObject.Horizontal,
              margin: new go.Margin(0, 0, 0, 0),
            },
            // 连接图标
            $(
              go.Picture, // flag image, only visible if a nation is specified
              {
                column: 0,
                margin: new go.Margin(0, 4, 0, 0),
                width: 25,
                height: 25,
                visible: true,
                // source: linkImg, // 打开页面会报错，不知道为啥？？？
              },
              new go.Binding('source', 'icon', theIconFlagConverter),
              new go.Binding('visible', 'icon', function (nat) {
                return nat !== undefined;
              })
            ),
            // 组件标题
            $(
              go.TextBlock,
              {
                column: 1,
                alignment: go.Spot.Left,
                name: 'TB',
                textAlign: 'left',
                font: '14px PingFangSC-Medium, arial, sans-serif',
                stroke: '#474A50',
                editable: false,
              },
              new go.Binding('text', 'title')
            )
          ),
          makeNodeDeleteButton()
        ),
        // 标题和内容的分割线
        $(
          go.Shape,
          'LineH',
          {
            margin: 0,
            minSize: new go.Size(lineMinWidth, NaN),
            stroke: '#E5E5E5',
            strokeWidth: 1,
            height: 1,
            stretch: go.GraphObject.Horizontal,
          },
          new go.Binding('visible').ofObject('INFO') // only visible when info is expanded
        ),
        // 话术文案
        $(
          go.TextBlock,
          {
            font: '12px Roboto, sans-serif',
            stroke: 'rgba(0, 0, 0, .60)',
            textAlign: 'center',
            margin: new go.Margin(10, 0, 0, 0), // 文案外边距
            maxSize: new go.Size(170, NaN),
            editable: false, // 是否可编辑
            visible: true, // 显示/隐藏
            alignment: go.Spot.Center,
            isMultiline: true, //是否多行
            //maxSize: new go.Size(1000, NaN)
          },
          new go.Binding('text', 'script', function (str) {
            return str || '请先编辑组件';
          })
        )
      ),

      // go.Node,
      // "Auto",
      // nodeStyle(),
      // {
      //   maxSize: new go.Size(100, 50),
      //   locationSpot: go.Spot.Top,
      //   isShadowed: true,
      //   shadowBlur: 1,
      //   shadowOffset: new go.Point(0, 1),
      //   shadowColor: "rgba(0, 0, 0, .14)",
      //   // selection adornment to match shape of nodes
      //   selectionAdornmentTemplate: $(
      //     go.Adornment,
      //     "Auto",
      //     $(go.Shape, "RoundedRectangle", roundedRectangleParams, {
      //       fill: null,
      //       stroke: "#1890ff",
      //       strokeWidth: 3,
      //     }),
      //     $(go.Placeholder)
      //   ), // end Adornment
      // },
      // $(
      //   go.Shape,
      //   "RoundedRectangle", // 边框
      //   { strokeWidth: 2, stroke: "#DEDEDE", fill: "white" }
      // ),
      // $(
      //   go.Shape,
      //   "RoundedRectangle", // 接点增强显示
      //   { strokeWidth: 5, stroke: "white", fill: "white" },
      //   new go.Binding("stroke", "status", nodeStatusConverter),
      //   new go.AnimationTrigger("stroke")
      // ),
      // $(
      //   go.TextBlock,
      //   {
      //     font: "15px Roboto, sans-serif",
      //     stroke: "rgba(0, 0, 0, .60)",
      //     textAlign: "center",
      //     margin: new go.Margin(0, 0, 0, 0),
      //     visible: true,
      //     editable: false,
      //     alignment: go.Spot.Center,
      //   },
      //   new go.Binding("text", "title")
      // ),
      // $(
      //   go.TextBlock,
      //   textStyle("script"),
      //   {
      //     textAlign: "center",
      //     margin: new go.Margin(30, 30, 10, 30),
      //     maxSize: new go.Size(200, NaN),
      //     editable: false,
      //     visible: true,
      //     alignment: go.Spot.Center,
      //     //maxSize: new go.Size(1000, NaN)
      //   },
      //   new go.Binding("text", "script").makeTwoWay()
      // ),
      makePort('T', go.Spot.Top, go.Spot.TopSide, false, true)
    )
  );

  const linkSelectionAdornmentTemplate = $(
    go.Adornment,
    'Link',
    $(go.Shape, {
      isPanelMain: true,
      fill: null,
      stroke: 'red',
      strokeWidth: 0,
    }) // 使用选择对象的strokeWidth
  );

  function linkStatusConverter(s: number) {
    if (s === 1) return '#1090ff';
    return 'transparent';
  }

  //  配置连线样式
  // replace the default Link template in the linkTemplateMap
  myDiagram.linkTemplate = $(
    go.Link, // the whole link panel
    {
      selectionAdornmentTemplate: linkSelectionAdornmentTemplate,
      //routing: go.Link.AvoidsNodes,
      //routing: go.Link.Orthogonal,
      curve: go.Link.Bezier,
      toEndSegmentLength: 80,
      fromEndSegmentLength: 80,
      corner: 10,
      curviness: 50,
      toShortLength: 4,
      relinkableFrom: true,
      relinkableTo: true,
      reshapable: true,
      resegmentable: true,
      zOrder: 2,
      // mouse-overs subtly highlight links:
      mouseEnter: function (e: go.InputEvent, link: go.GraphObject) {
        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
        link.findObject('HIGHLIGHT').stroke = 'rgba(30,144,255,0.2)';
      },
      mouseLeave: function (e: go.InputEvent, link: go.GraphObject) {
        // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
        link.findObject('HIGHLIGHT').stroke = 'transparent';
      },
      selectionAdorned: false,
    },
    new go.Binding('points').makeTwoWay(),
    $(
      go.Shape, // the highlight shape, normally transparent 链接线的背景区域，通常是透明的
      {
        isPanelMain: true,
        strokeWidth: 5,
        stroke: 'transparent',
        name: 'HIGHLIGHT',
      },
      new go.Binding('stroke', 'status', linkStatusConverter) // 连线增强显示
      // new go.AnimationTrigger("stroke")
    ),
    $(
      go.Shape, // the link path shape 链接线的形状
      { isPanelMain: true, stroke: '#c9c9c9', strokeWidth: 2 },
      new go.Binding('stroke', 'isSelected', function (sel) {
        return sel ? 'dodgerblue' : '#c9c9c9';
      }).ofObject()
    ),
    $(
      go.Shape, // the arrowhead 箭头
      { toArrow: 'standard', strokeWidth: 0, fill: '#c9c9c9' }
    ),
    $(
      go.Panel,
      'Auto', // the link label, normally not visible 链接标签，通常不可见
      {
        visible: false,
        name: 'LABEL',
        segmentIndex: 2,
        segmentFraction: 0.5,
      },
      new go.Binding('visible', 'visible').makeTwoWay(),
      $(
        go.Shape,
        'RoundedRectangle', // the label shape
        { fill: '#F8F8F8', strokeWidth: 0 }
      ),
      $(
        go.TextBlock,
        'Yes', // the label
        {
          textAlign: 'center',
          font: '10pt helvetica, arial, sans-serif',
          stroke: '#333333',
          editable: true,
        },
        new go.Binding('text').makeTwoWay()
      )
    )
  );
  // Make link labels visible if coming out of a "conditional" node.
  // This listener is called by the "LinkDrawn" and "LinkRelinked" DiagramEvents.
  // function showLinkLabel(e) {
  //   var label = e.subject.findObject("LABEL");
  //   if (label !== null)
  //     label.visible = e.subject.fromNode.data.category === "Conditional";
  // }

  // temporary links used by LinkingTool and RelinkingTool are also orthogonal:
  myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
  myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
  // load(); // load an initial diagram from some JSON text
  const myPalette = $(go.Palette, {
    //用Gridlayout格子布局垂直排列每行数据
    contentAlignment: go.Spot.TopLeft,
    layout: $(go.TreeLayout, { nodeSpacing: 3 }),
    isReadOnly: true, // 禁止编辑
    maxSelectionCount: 1,
    'animationManager.initialAnimationStyle': go.AnimationManager.None,
    InitialAnimationStarting: animateFadeDown,
  });

  myPalette.nodeTemplate = $(
    go.Node,
    'Horizontal',
    {
      locationObjectName: 'TB',
      locationSpot: go.Spot.Center,
    },
    $(
      go.Panel,
      'Horizontal',
      { alignment: go.Spot.Left },
      $(
        go.Picture, // flag image, only visible if a nation is specified
        { margin: mr8, width: 30, height: 30, source: linkImg },
        new go.Binding('source', 'icon', theIconFlagConverter),
        new go.Binding('visible', 'icon', function (nat) {
          return nat !== undefined;
        })
      ),
      $(
        go.TextBlock,
        {
          name: 'TB',
          textAlign: 'left',
          font: '14px PingFangSC-Medium, arial, sans-serif',
          stroke: '#474A50',
          editable: true,
        },
        new go.Binding('text', 'title')
      )
    )
  );

  // This is a re-implementation of the default animation, except it fades in from downwards, instead of upwards.
  function animateFadeDown(e: any) {
    const diagram = e.diagram;
    const animation = new go.Animation();
    animation.isViewportUnconstrained = true; // So Diagram positioning rules let the animation start off-screen
    animation.easing = go.Animation.EaseOutExpo;
    animation.duration = 900;
    // Fade "down", in other words, fade in from above
    animation.add(diagram, 'position', diagram.position.copy().offset(0, 200), diagram.position);
    animation.add(diagram, 'opacity', 0, 1);
    animation.start();
  }

  myDiagram.model = $(go.GraphLinksModel, {
    // class: "GraphLinksModel",
    linkKeyProperty: 'key', // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
    linkFromPortIdProperty: 'fromPort', // 解决连线断开
    linkToPortIdProperty: 'toPort', // 解决连线断开
    copiesArrays: false,
    copiesArrayObjects: false,
    // negative keys for links
    // 生成链接的唯一key
    makeUniqueLinkKeyFunction: (m: go.GraphLinksModel, data: any) => {
      let k = data.key || -1;
      while (m.findLinkDataForKey(k)) k--;
      data.key = k;
      return k;
    },
    makeUniqueKeyFunction: (m: go.Model, data: any) => {
      let k = data.key || 1;
      while (m.findNodeDataForKey(k)) k++;
      data.key = k;
      return k;
    },
    // nodeDataArray: nodedata,
    // linkDataArray: linkdata,
    // linkKeyProperty: "key",
  });

  return myDiagram;
}
